package com.rzhd.coursepatriarch.common.utils.rxbus;

import java.util.HashMap;

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;

/**
 * @author yql
 * @date: 2018/7/11.
 */
public class RxBus {

    private static volatile RxBus instance;

    private final Subject<Object> mBus;
    /**
     * 保存订阅后的disposable
     */
    private HashMap<String, CompositeDisposable> mSubscriptionMap;


    public RxBus() {
        mBus = PublishSubject.create().toSerialized();
    }

    public static RxBus getInstance() {
        if (instance == null) {
            synchronized (RxBus.class) {
                if (instance == null) {
                    instance = new RxBus();
                }
            }
        }
        return instance;
    }

    public void post(@RxBusBaseMessage.EventCode int code, Object object) {
        //判断当前是否已经添加订阅
        if (mBus.hasObservers()) {
            mBus.onNext(new RxBusBaseMessage(code, object));
        }
    }

//    /**
//     * 根据传递的code和evenType类型返回特定类型（evenType）的 被观察者
//     * 对于注册了code = 0 ，class为RxBusBaseMessage的观察者，那么久接收不到code = 1的RxBusBaseMessage
//     *
//     * @param code
//     * @param evenType
//     * @param <T>
//     * @return
//     */
//    public <T> Observable<T> toObservable(@RxBusBaseMessage.EventCode final int code, final Class<T> evenType) {
//        return mBus.ofType(RxBusBaseMessage.class).filter(new Predicate<RxBusBaseMessage>() {
//            @Override
//            public boolean test(RxBusBaseMessage rxBusBaseMessage) throws Exception {
//                return rxBusBaseMessage.getCode() == code && evenType.isInstance(rxBusBaseMessage.getObject());
//            }
//        }).map(new Function<RxBusBaseMessage, Object>() {
//            @Override
//            public Object apply(RxBusBaseMessage rxBusBaseMessage) throws Exception {
//                return rxBusBaseMessage.getObject();
//            }
//        }).cast(evenType);
//    }

    /**
     * 由于需要取消订阅  将Observable替换成
     * 根据传递的code和evenType类型返回特定类型（evenType）的 被观察者
     * 对于注册了code = 0 ，class为RxBusBaseMessage的观察者，那么久接收不到code = 1的RxBusBaseMessage
     *
     * @param code     事件code
     * @param evenType 事件类型
     * @param next     返回数据
     * @param error    错误解析
     * @param <T>
     * @return
     */
    public <T> Disposable toObservable(@RxBusBaseMessage.EventCode final int code, final Class<T> evenType, Consumer<T> next, Consumer<Throwable> error) {
        return mBus.ofType(RxBusBaseMessage.class).filter(new Predicate<RxBusBaseMessage>() {
            @Override
            public boolean test(RxBusBaseMessage rxBusBaseMessage) throws Exception {
                //过滤code和eventType都相同的事件
                boolean aaa = rxBusBaseMessage.getCode() == code;
                boolean bbb = evenType.isInstance(rxBusBaseMessage.getObject());
                return aaa && bbb;
            }
        }).map(new Function<RxBusBaseMessage, Object>() {
            @Override
            public Object apply(RxBusBaseMessage rxBusBaseMessage) throws Exception {
                return rxBusBaseMessage.getObject();
            }
        }).cast(evenType).subscribe(next, error);
    }

    /**
     * 判断是否有订阅者
     *
     * @return
     */
    public boolean hasSubscribers() {
        return mBus.hasObservers();
    }

    /**
     * 保存订阅后的 disposable
     *
     * @param o
     * @param disposable
     */
    public void addSubscription(Object o, Disposable disposable) {
        if (disposable == null) {
            return;
        }
        if (mSubscriptionMap == null) {
            mSubscriptionMap = new HashMap<>();
        }
        String key = o.getClass().getName();
        if (mSubscriptionMap.get(key) != null) {
            mSubscriptionMap.get(key).add(disposable);
        } else {
            //一次性容器，可以持有多个并提供 添加和删除
            CompositeDisposable compositeDisposable = new CompositeDisposable();
            compositeDisposable.add(disposable);
            mSubscriptionMap.put(key, compositeDisposable);
        }
    }

    /**
     * 取消订阅
     *
     * @param o 这个是添加到订阅的对象
     */
    public void unSubscribe(Object o) {
        if (mSubscriptionMap == null) {
            return;
        }
        String key = o.getClass().getName();
        if (!mSubscriptionMap.containsKey(key)) {
            return;
        }
        if (mSubscriptionMap.get(key) != null) {
            mSubscriptionMap.get(key).dispose();
        }
        mSubscriptionMap.remove(key);
    }

}
